//
//  ApplePay.swift
//  tappay_charge
//
//  Created by Warren L on 2024/7/17.
//

import Foundation
import TPDirect

typealias AppPayCommonCallback = (TappaySdkCommonResult) -> Void

typealias ApplePayPaymentCallback = (TappayPaymentResult) -> Void

class ApplePay: NSObject {
    /// 支付
    var applePay: TPDApplePay?
    /// 商家
    var merchant : TPDMerchant!
    /// 消費者
    var consumer: TPDConsumer!
    /// 購物車
    var cart: TPDCart!

    /// 支付是否正在進行
    private var isPaymentProcessing: Bool = false
    
    /// 支付回調
    private var onApplePayResult: ApplePayPaymentCallback?
    
    /// 初始化ApplePay
    func initApplePay(
        merchantId: String,
        merchantName: String,
        currencyCode: String? = nil,
        countryCode: String? = nil,
        supportedCardTypes: [String]?,
        callback: AppPayCommonCallback?
    ) {
        /// 檢測是否有正在進行的支付
        if (isPaymentProcessing) {
            let errorResult = TappaySdkCommonResult(success: false, message: "Previous payment is still processing")
            callback?(errorResult)
            return
        }
        
        /// 商家
        merchant = TPDMerchant()
        /// 商家ID
        merchant.applePayMerchantIdentifier = merchantId
        /// 商家名稱
        merchant.merchantName = merchantName
        /// 國家代碼
        merchant.countryCode = countryCode
        /// 貨幣代碼
        merchant.currencyCode = currencyCode
        /// 商家支持的支付能力，3DS 是必須支持的
        merchant.merchantCapability = [.credit, .debit, .threeDSecure, .emv];
        /// 商家支持的卡類型
        var supportNetworks = convertCardTypes(cardTypes: supportedCardTypes)
        if (supportNetworks.isEmpty) {
            supportNetworks = [.visa, .masterCard, .amex, .JCB]
        }
        merchant.supportedNetworks = supportNetworks

        
        /// 消费者
        consumer = TPDConsumer()
        

        let successResult = TappaySdkCommonResult(success: true, message: "Apple Pay init successful")
        callback?(successResult)
    }
    
    /// 發起ApplePay
    func startApplePay(
        isAmountPending: Bool,
        isShowTotalAmount: Bool,
        cartItems: [[String: Any]],
        onApplePayResult: ApplePayPaymentCallback?
    ) {
        /// 檢測是否有正在進行的支付
        if (isPaymentProcessing) {
            let errorResult = TappayPaymentResult(success: false, status: nil, message: "Previous payment is still processing.", prime: nil)
            onApplePayResult?(errorResult)
            return
        }
        
        /// 检测商品是否为空
        let items = cartItems.compactMap { CartItem.fromDictionary($0) }
        if (items.isEmpty) {
            let errorResult = TappayPaymentResult(success: false, status: nil, message: "Missing required parameters cartItems for startApplePay method.", prime: nil)

            onApplePayResult?(errorResult)
            return
        }
        
        self.onApplePayResult = onApplePayResult
        
        /// 购物车
        cart = TPDCart()
        /// 是否延期付款
        cart.isAmountPending = isAmountPending
        /// 是否显示总金额或待处理金额
        cart.isShowTotalAmount = isShowTotalAmount
        /// 添加商品
        for item in items {
            if item.isPending ?? false {
                let paymentItem = TPDPaymentItem.pendingPaymentItem(withItemName: item.name)
                cart.add(paymentItem)
            } else {
                let paymentItem = TPDPaymentItem(itemName: item.name, withAmount: NSDecimalNumber(string: String(item.price)), withIsVisible: true)
                cart.add(paymentItem)
            }
        }
        
        /// 發起支付
        applePay = TPDApplePay.setupWthMerchant(merchant, with: consumer, with: cart, withDelegate: self)
        applePay?.startPayment()
    }
    
    /// 顯示ApplePay支付結果
    func showApplePayResult(
        result: Bool,
        callback: AppPayCommonCallback?
    ) {
        /// 檢測是否有支付在進行
        if (!isPaymentProcessing) {
            let errorResult = TappaySdkCommonResult(success: false, message: "No payment is processing.")
            callback?(errorResult)
            return
        }
        
        /// 檢測是否先發起支付了
        if (applePay == nil) {
            let errorReuslt = TappaySdkCommonResult(success: false, message: "Please startApplePay first")
            callback?(errorReuslt)
            return
        }
        
        applePay?.showPaymentResult(result)
        
        let successResult = TappaySdkCommonResult(success: true, message: nil)
        callback?(successResult)
    }
    
    private func convertCardTypes(cardTypes: [String]?) -> [PKPaymentNetwork] {
        return cardTypes?.compactMap { mapCardType(cardTypeString: $0) } ?? []
    }
    
    private func mapCardType(cardTypeString: String) -> PKPaymentNetwork? {
        switch cardTypeString {
        case "visa":
            return .visa
        case "masterCard":
            return .masterCard
        case "amex":
            return .amex
        case "jcb":
            return .JCB
        case "chinaUnionPay":
            return .chinaUnionPay
        case "discover":
            return .discover
        default:
            return nil
        }
    }
}

extension ApplePay : TPDApplePayDelegate {
    /// 開始調起支付的回調（付款彈窗出現）
    func tpdApplePayDidStartPayment(_ applePay: TPDApplePay!) {
        //
        print("=====================================================")
        print("Apple Pay On Start")
        print("===================================================== \n\n")
        
        isPaymentProcessing = true
    }
    
    /// 支付完成的回調（付款彈窗消失）
    func tpdApplePayDidFinishPayment(_ applePay: TPDApplePay!) {
        //
        print("=====================================================")
        print("Apple Pay Did Finish")
        print("===================================================== \n\n")
        
        isPaymentProcessing = false
    }
    
    /// 支付成功的回調
    func tpdApplePay(_ applePay: TPDApplePay!, didSuccessPayment result: TPDTransactionResult!) {
        //
        print("=====================================================")
        print("Apple Pay Did Success ==> Amount : \(result.amount.stringValue)")
        print("===================================================== \n\n")
    }
    
    /// 支付失敗的回調
    func tpdApplePay(_ applePay: TPDApplePay!, didFailurePayment result: TPDTransactionResult!) {
        //
        print("=====================================================")
        print("Apple Pay Did Failure ==> Message : \(result.message), ErrorCode : \(result.status)")
        print("===================================================== \n\n")
        
        let errorResult = TappayPaymentResult(success: false, status: result.status, message: result.message, prime: nil)
        onApplePayResult?(errorResult)
    }
    
    /// 用戶取消支付的回調
    func tpdApplePayDidCancelPayment(_ applePay: TPDApplePay!) {
        //
        print("=====================================================")
        print("Apple Pay Did Cancel")
        print("===================================================== \n\n")
        
        
        let errorResult = TappayPaymentResult(success: false, status: -99, message: "Apple Pay payment was canceled", prime: nil)
        onApplePayResult?(errorResult)
    }
    
    
    /// 支付收到prime的回調，
    /// 將prime傳給後台服務器完成交易，完成後呼叫showPaymentResult方法來顯示結果
    func tpdApplePay(_ applePay: TPDApplePay!, didReceivePrime prime: String!, withExpiryMillis expiryMillis: Int, with cardInfo: TPDCardInfo, withMerchantReferenceInfo merchantReferenceInfo: [AnyHashable : Any]!) {
        // 1. Send Your Prime To Your Server, And Handle Payment With Result
        // ...
        print("=====================================================");
        print("======> didReceivePrime");
        print("Prime : \(prime!)");
        print("Expiry millis : \(expiryMillis)");
        print("total Amount :   \(applePay.cart.totalAmount!)")
        print("Client IP : \(applePay.consumer.clientIP!)")
        print("merchantReferenceInfo : \(merchantReferenceInfo["affiliateCodes"]!)")
        print("===================================================== \n\n");

//        // 2. If Payment Success, set paymentReault = ture.
//        let paymentReault = true;
//        applePay.showPaymentResult(paymentReault)
        
        
        let successResult = TappayPaymentResult(success: true, status: nil, message: "Apple Pay payment was successful", prime: prime)
        onApplePayResult?(successResult)
    }
}
